Portfolio performance and key metrics¶

Code written by Vala "Valatility" Zeinali and Lev "l3v" Thierbach¶

In [1]:
import yfinance as yf
import numpy as np
import pandas as pd
from pandas_datareader import data as pdr
from matplotlib import pyplot as plt
import plotly.graph_objects as go
import warnings
import statistics as stats
warnings.filterwarnings("ignore")
In [2]:
start_date = "2023-01-05"
end_date = "2023-12-12"
In [3]:
tickers = ["ARGT","AVTR","HCC","DHR","TMF","VZ","USO","TTWO","SHY","MBB","GLD","EWZ","EA","CTLT","SPY"]
In [4]:
wts = [
 0.7
,0.01
,0.3
,0.01
,0.24
,0.02
,0.23
,0.01
,0.10
,0.13
,0.7
,0.7
,0.01
,0.01
,0.000
]
In [5]:
yf.pdr_override()

price_data = pdr.get_data_yahoo(tickers,
                               start = start_date,
                               end = end_date)
[*********************100%***********************]  15 of 15 completed
In [6]:
price_data = price_data['Adj Close']
In [7]:
ret_data = price_data.pct_change()[1:]
In [8]:
weighted_returns = (wts * ret_data)
In [9]:
weighted_returns = weighted_returns.reset_index()
weighted_returns.head()
Out[9]:
Date ARGT AVTR CTLT DHR EA EWZ GLD HCC MBB SHY SPY TMF TTWO USO VZ
0 2023-01-06 0.019792 -0.000276 0.009682 -0.000107 -0.001521 0.000771 0.004303 0.000375 0.001292 0.000496 0.016052 0.038017 -0.000114 0.000008 0.0
1 2023-01-09 0.011195 0.000294 0.003273 0.000101 0.000542 -0.000148 0.000516 -0.000292 0.000295 0.000128 -0.000397 0.010190 0.000033 0.000162 -0.0
2 2023-01-10 0.004446 0.000392 -0.000498 0.000464 -0.000290 0.000520 0.000845 0.000113 -0.000410 -0.000112 0.004909 -0.033223 0.000041 0.000003 0.0
3 2023-01-11 0.015368 0.000331 0.008482 0.000259 0.004045 0.000458 -0.000158 0.000021 0.000697 0.000112 0.008854 0.032445 -0.000026 0.000326 -0.0
4 2023-01-12 0.020489 -0.000023 -0.000667 -0.000055 0.000590 0.000170 0.002661 -0.000068 0.000702 0.000287 0.002549 0.040310 -0.000092 0.000082 0.0
In [10]:
# Calculate portfolio returns
port_ret = weighted_returns.drop("Date", axis=1).sum(axis=1)
# axis =1 tells pandas we want to add
In [11]:
cumulative_ret = ((port_ret + 1).cumprod()) - 1
In [12]:
fig1 = go.Figure() # go object

MHF = cumulative_ret
SPY = ((ret_data["SPY"] + 1).cumprod()) - 1



fig1.add_trace(go.Scatter(x=weighted_returns["Date"],y=MHF, name='Valatility Return',
                         line=dict(color='royalblue', width=3,)))
fig1.add_trace(go.Scatter(x=weighted_returns["Date"], y=SPY, name='SPY',
                        line=dict(color='green', width=3,)))

# Edit the layout
fig1.update_layout(title=f'Mock Hedgefund {(MHF.tail(1).values *100).round(2)}% vs SPY {(SPY.tail(1).values *100).round(2)}% - 2023',
                   xaxis_title='Year',
                   yaxis_title='Cumulative Return', width=1000, height=800,)
fig1.show()
In [13]:
Alpha = (MHF.tail(1).values *100).round(2) - (SPY.tail(1).values *100).round(2)
In [14]:
Beta = stats.covariance(MHF, SPY) / stats.variance(SPY)
In [15]:
# Calculate the Sharpe Ratio
sharpe_ratio = np.mean(MHF) / np.std(MHF)

# Annualize the Sharpe Ratio
annual_factor = np.sqrt(252)  # Use 252 for daily returns, 52 for weekly returns, 12 for monthly returns
sharpe_ratio_annu = sharpe_ratio * annual_factor

Alpha

In [16]:
alpha_values = []
asset_names = []


# Calculate Alpha for each asset
for asset in tickers:
    asset_returns = ret_data[asset]
    
    risk_free_rate = 0.00 
    excess_return = asset_returns - risk_free_rate
    alpha = (excess_return.mean() * 252) * 100  # % Annualized Alpha
    asset_names.append(asset)
    alpha_values.append(alpha)

# Create a df to hold Asset and Alpha values
alpha_df = pd.DataFrame({'Asset': asset_names, 'Alpha': alpha_values})

Beta

In [17]:
beta_values = []

# Calculate Beta for each asset
for asset in tickers:
        asset_returns = ret_data[asset]
        covar = stats.covariance(asset_returns, SPY)
        var = stats.variance(SPY)
        beta = covar / var
        beta_values.append(beta)
    

# Create a df to hold Asset and Beta values
beta_df = pd.DataFrame({'Asset': tickers, 'Beta': beta_values})

Plot Alpha

In [18]:
fig = go.Figure()

fig.add_trace(go.Scatter(
    x=alpha_values, y=asset_names,
    name='Alpha',
    mode='markers',
    marker_color= alpha_values
    
    )
)

fig.update_layout(title='Alpha| Asset vs. Benchmark(SPY) for Portfolio Assets - 2023',
                  yaxis_title='Ticker', width=1000, height=800,
                  xaxis_title='Alpha Values')
fig.update_traces(mode='markers', marker_line_width=1, marker_size=15)
                
fig.show()

Plot Beta

In [19]:
fig = go.Figure()

fig.add_trace(go.Scatter(
    x=beta_values, y=tickers,
    name='Beta',
    mode='markers',
    marker_color= beta_values
    
    )
)

fig.update_layout(title='Beta| Asset vs. Benchmark(SPY) for Portfolio Assets - 2023',
                 yaxis_title='Ticker', width=1000, height=800,
                  xaxis_title='Beta Values')
fig.update_traces(mode='markers', marker_line_width=1, marker_size=15)
fig.show()

Metrics

In [20]:
print(f'Annualized Sharpe Ratio (2023): {round(sharpe_ratio_annu, 2)}%')
Annualized Sharpe Ratio (2023): 39.72%
In [21]:
print(f'2023 Yearly Alpha: {round(Alpha[0], 2)}%')
2023 Yearly Alpha: 4.59%
In [22]:
print(f'2023 Yearly Beta: {round(Beta, 2)}')
2023 Yearly Beta: 0.54